home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Display Manager / Display Manager Sample Code / DMFkey Source / RequestVideo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-24  |  25.7 KB  |  699 lines  |  [TEXT/CWIE]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    MacOS™ Sample Code
  4. #    
  5. #    Written by: Eric Anderson
  6. #    email: eric3@apple.com
  7. #
  8. #    Display Manager sample code
  9. #
  10. #    RequestVideo
  11. #
  12. #    RequestVideo.c    -    C Code
  13. #
  14. #    Copyright © 1995 Apple Computer, Inc.
  15. #    All rights reserved.
  16. #
  17. #    5/31/95        ewa        Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
  18. #                        to make it easy to revert back to where you came from and to give
  19. #                        the user a chance to confirm the new setting if the new mode was
  20. #                        valid (ie: the card supports it) but not safe (the monitor may not).
  21. #    5/24/95        ewa        Give the kAllValidModesBit requestFlags option for safe only or all
  22. #                        valid resolution timings.
  23. #
  24. #
  25. #
  26. #    Components:    PlayVideo.c            
  27. #                RequestVideo.c        
  28. #                RequestVideo.h        
  29. #                RequestVideo.rsrc        
  30. #
  31. #    RequestVideo demonstrates the usage of the Display Manager introduced
  32. #    with the PowerMacs and integrated into the system under System 7.5. With
  33. #    the RequestVideo sample code library, developers will be able to explore
  34. #    the Display Manager API by changing bit depth and screen resolution on
  35. #    multisync displays on built-in, NuBus, and PCI based video. Display Manager 1.0
  36. #    is built into the Systems included with the first PowerMacs up through System 7.5.
  37. #    Display Manager 2.0 is included with the release of the new PCI based PowerMacs,
  38. #    and will be included in post 7.5 System Software releases. 
  39. #    
  40. #    It is a good idea to reset the screen(s) to the original setting before exit
  41. #    since the call to RVSetVideoAsScreenPrefs() may not do the right thing under
  42. #    Display Manager 1.0 with certain video drivers.
  43. #
  44. #    For information on the use of this sample code, please the documentation in the Read Me file
  45. ------------------------------------------------------------------------------*/
  46.  
  47. #include "RequestVideo.h"
  48.  
  49. // Internal includes
  50. #include <Dialogs.h>
  51. #include <ROMDefs.h>
  52. #include <Devices.h>
  53. #include <Errors.h>
  54. #include <Gestalt.h>
  55. #include <Memory.h>
  56. #include <Palettes.h>
  57. #include <Slots.h>
  58. #include <StdIO.h>
  59. #include <Displays.h>
  60.  
  61. #include <stdlib.h>
  62.  
  63. //--------------------------------------------------------------
  64. //
  65. // Internal defines, structs, typedefs, and routine declarations
  66. //
  67. //--------------------------------------------------------------
  68. #define        KMonoDev            0                        // false (handy definitions for gdDevType settings)
  69. #define        kColorDev            1                        // true
  70. #define        char_Enter            0x03                    // for our filter proc
  71. #define        char_Return            0x0D                    //
  72. #define        iRevertItem            1                        // User buttons
  73. #define        iConfirmItem        2                        //
  74. #define        kSecondsToConfirm    8                        // seconds before confirm dialog is taken down
  75. #define        rConfirmSwtchAlrt    2735                    // ID of alert dialog
  76.  
  77. struct DepthInfo {
  78.     VDSwitchInfoRec            depthSwitchInfo;            // This is the switch mode to choose this timing/depth
  79.     VPBlock                    depthVPBlock;                // VPBlock (including size, depth and format)
  80. };
  81. typedef struct DepthInfo DepthInfo;
  82.  
  83. struct ListIteratorDataRec {
  84.     VDTimingInfoRec            displayModeTimingInfo;        // Contains timing flags and such
  85.     unsigned long            depthBlockCount;            // How many depths available for a particular timing
  86.     DepthInfo                *depthBlocks;                // Array of DepthInfo
  87. };
  88. typedef struct ListIteratorDataRec ListIteratorDataRec;
  89.  
  90. void GetRequestTheDM1Way (        VideoRequestRecPtr requestRecPtr,
  91.                                 GDHandle walkDevice);
  92.  
  93. void GetRequestTheDM2Way (        VideoRequestRecPtr requestRecPtr,
  94.                                 GDHandle walkDevice,
  95.                                 DMDisplayModeListIteratorUPP myModeIteratorProc,
  96.                                 DMListIndexType theDisplayModeCount,
  97.                                 DMListType *theDisplayModeList);
  98.  
  99. pascal void ModeListIterator (    void *userData,
  100.                                 DMListIndexType itemIndex,
  101.                                 DMDisplayModeListEntryPtr displaymodeInfo);
  102.  
  103. Boolean FindBestMatch (            VideoRequestRecPtr requestRecPtr,
  104.                                 short bitDepth,
  105.                                 unsigned long horizontal,
  106.                                 unsigned long vertical);
  107.  
  108. void GravitateMonitors (void);
  109.  
  110. pascal Boolean ConfirmAlertFilter (DialogPtr dlg, EventRecord *evt, short *itemHit);
  111.  
  112. //--------------------------------------------------------------
  113. //
  114. // Implementation of sample code
  115. //
  116. //--------------------------------------------------------------
  117. OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
  118. {
  119.     GDHandle        aMonitor;
  120.     Boolean            displayMgrPresent;
  121.     unsigned long    displayMgrVersion;
  122.     OSErr            err;
  123.     Boolean            isColor;
  124.     long            value = 0;
  125.  
  126.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  127.     Gestalt(gestaltDisplayMgrAttr,&value);
  128.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  129.     if (displayMgrPresent)
  130.     {
  131.         if (requestRecPtr->displayMode && requestRecPtr->depthMode)
  132.         {
  133.             if (requestRecPtr->availBitDepth == 1)    // Based on avail bit depth, 
  134.                 isColor = KMonoDev;                    // set the device to a mono device, or
  135.             else isColor = kColorDev;                // set the device to a color device
  136.             SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);        
  137.             
  138.             // see how many monitors we have, aMonitor will be nil if we have only one.
  139.             aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // get the first guy
  140.             aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );    // get the next guy
  141.             
  142.             if (nil == aMonitor || displayMgrVersion >= 0x00020000)
  143.             {
  144.                 // only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
  145.                 // since DM1.0 does not automatically gravitate monitors and our gravitate code
  146.                 // is not implemented.
  147.                 err = DMSetDisplayMode(    requestRecPtr->screenDevice,    // GDevice
  148.                         requestRecPtr->displayMode,                        // DM1.0 uses this
  149.                         &requestRecPtr->depthMode,                        // DM1.0 uses this
  150.                         (unsigned long) &(requestRecPtr->switchInfo),    // DM2.0 uses this rather than displayMode/depthMode combo
  151.                         nil);
  152.                 if (noErr == err)
  153.                 {
  154.                     // Do the monitor gravitate here if we are using a version less than DM2.0
  155.                     if (displayMgrVersion < 0x00020000)
  156.                         GravitateMonitors ();
  157.                 }
  158.                 else if (kDMDriverNotDisplayMgrAwareErr == err)
  159.                 {
  160.                     // DM not supported by driver, so all we can do is set the bit depth
  161.                     err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  162.                 }
  163.             }
  164.             else
  165.             {
  166.                 // we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
  167.                 err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  168.             }
  169.             
  170.             return (err);    // we did try to set the request
  171.         }
  172.     }
  173.     return (-1);    // return a generic error
  174. }
  175.  
  176. // This extern should be removed once this function is formally defined in Displays.h
  177. extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
  178.  THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);
  179.  
  180. OSErr RVSetVideoAsScreenPrefs (void)
  181. {
  182.     Handle        displaystate;
  183.     Boolean        displayMgrPresent;
  184.     long        value = 0;
  185.  
  186.     Gestalt(gestaltDisplayMgrAttr,&value);
  187.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  188.     if (displayMgrPresent)
  189.     {
  190.         DMBeginConfigureDisplays (&displaystate);    // Tell the world it is about to change
  191.         DMUseScreenPrefs (true, displaystate);        // Make the change
  192.         DMEndConfigureDisplays (displaystate);        // Tell the world the change is over
  193.         
  194.         return (noErr);    // we (maybe) set the world back to a known setting
  195.     }
  196.     return (-1);    // return a generic error
  197. }
  198.  
  199. OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
  200. {
  201.     unsigned long        displayMgrVersion;
  202.     OSErr                error = paramErr;
  203.     CntrlParam            pBlock;
  204.     VDSwitchInfoRec        switchInfo;
  205.     AuxDCEHandle        theDCE;
  206.     VDSwitchInfoRec        videoMode;        
  207.  
  208.     requestRecPtr->availBitDepth            = 0;    // init to default - you can do it if it is important to you
  209.     requestRecPtr->availHorizontal            = 0;
  210.     requestRecPtr->availVertical            = 0;
  211.     requestRecPtr->availFlags                = 0;
  212.     requestRecPtr->displayMode                = -1; 
  213.     requestRecPtr->depthMode                = -1;
  214.     requestRecPtr->switchInfo.csMode        = 0;
  215.     requestRecPtr->switchInfo.csData        = 0;
  216.     requestRecPtr->switchInfo.csPage        = 0;
  217.     requestRecPtr->switchInfo.csBaseAddr    = 0;
  218.     requestRecPtr->switchInfo.csReserved    = 0;
  219.     
  220.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  221.     if (requestRecPtr->screenDevice)
  222.     {
  223.         if (displayMgrVersion >= 0x00020000)
  224.         {    // get the info the DM 2.0 way
  225.             error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
  226.             if (noErr == error)
  227.             {
  228.                 requestRecPtr->depthMode            = switchInfo.csMode;
  229.                 requestRecPtr->displayMode            = switchInfo.csData; 
  230.                 requestRecPtr->switchInfo.csMode    = switchInfo.csMode;
  231.                 requestRecPtr->switchInfo.csData    = switchInfo.csData;
  232.             }
  233.             return (error);    // we (maybe) set the world back to a known setting
  234.         }
  235.         else
  236.         {    // get the info the DM 1.0 way
  237.             videoMode.csMode = -1;        // init to bogus value
  238.             videoMode.csData = -1;        // init to bogus value            
  239.             pBlock.ioNamePtr = nil;
  240.             pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
  241.             pBlock.csCode = cscGetCurMode;
  242.             *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
  243.                 
  244.             error = PBStatusSync((ParmBlkPtr )&pBlock);    // ask the driver first....since we trust it the most
  245.                 
  246.             if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
  247.                 error = statusErr;
  248.             
  249.             if (noErr != error)    // if the driver has no clue fill it videoMode by hand as a last resort
  250.             {    
  251.                 theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
  252.                 
  253.                 if( theDCE )
  254.                 {
  255.                     videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
  256.                     videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
  257.                     error = noErr;
  258.                 }
  259.             }
  260.             if (noErr == error)    // Set our data
  261.             {
  262.                 requestRecPtr->displayMode            = videoMode.csData; 
  263.                 requestRecPtr->depthMode            = videoMode.csMode;
  264.                 requestRecPtr->switchInfo.csMode    = videoMode.csMode;
  265.                 requestRecPtr->switchInfo.csData    = videoMode.csData;
  266.             }
  267.             return (error);    // we (maybe) set the world back to a known setting
  268.         }
  269.     }
  270.     return (-1);
  271. }
  272.  
  273. pascal Boolean ConfirmAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  274. {
  275.     char charCode;
  276.     Boolean enterORreturn;
  277.     Boolean returnValue = false;
  278.  
  279.     if (0 == GetWRefCon(theDialog))
  280.         SetWRefCon (theDialog,TickCount());
  281.     else
  282.     {
  283.         if (GetWRefCon(theDialog) + kSecondsToConfirm * 60 < TickCount())
  284.         {
  285.             returnValue = true;
  286.             theEvent->what = nullEvent;
  287.             *itemHit = 1;
  288.         }
  289.         else
  290.         {
  291.             if (theEvent->what == keyDown)
  292.             {
  293.                 charCode = (char)theEvent->message & charCodeMask;
  294.                 enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
  295.                 if (enterORreturn)
  296.                 {
  297.                     theEvent->what = nullEvent;
  298.                     returnValue = true;
  299.                     *itemHit = iRevertItem;
  300.                     if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
  301.                     {
  302.                         *itemHit = iConfirmItem;
  303.                     }
  304.                 }
  305.             }
  306.         }
  307.     }
  308.     return (returnValue);
  309. }
  310.  
  311. OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
  312. {
  313.     short            alertReturn;        // Alert() return value
  314.     ModalFilterUPP    confirmFilterUPP;    // got to have us one of them new fangled UPP thingies
  315.     
  316.     if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
  317.     {    // new mode is valid but not safe, so ask user to confirm
  318.         SetCursor(&qd.arrow);                                        // have to show the arrow
  319.  
  320.         confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);    // create a new modal filter proc UPP
  321.         alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);    // alert the user
  322.         DisposeRoutineDescriptor (confirmFilterUPP);                // of course there is no DisposeModalFilterProc...
  323.         
  324.         if (alertReturn != iConfirmItem)
  325.             return (-1);                            // tell the caller to switch back to a known setting
  326.         else return (noErr);                        // all is well with the new setting, just leave it
  327.     }
  328.     return (noErr);                                    // the mode was safe, so do nothing
  329. }
  330.  
  331.  
  332. OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
  333. {
  334.     Boolean                            displayMgrPresent;
  335.     short                            iCount = 0;                    // just a counter of GDevices we have seen
  336.     DMDisplayModeListIteratorUPP    myModeIteratorProc = nil;    // for DM2.0 searches
  337.     SpBlock                            spBlock;
  338.     Boolean                            suppliedGDevice;    
  339.     DisplayIDType                    theDisplayID;                // for DM2.0 searches
  340.     DMListIndexType                    theDisplayModeCount;        // for DM2.0 searches
  341.     DMListType                        theDisplayModeList;            // for DM2.0 searches
  342.     long                            value = 0;
  343.     GDHandle                        walkDevice = nil;            // for everybody
  344.  
  345.     Gestalt(gestaltDisplayMgrAttr,&value);
  346.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  347.     displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);    // need slot manager
  348.     if (displayMgrPresent)
  349.     {
  350.         // init the needed data before we start
  351.         if (requestRecPtr->screenDevice)                            // user wants a specifc device?
  352.         {
  353.             walkDevice = requestRecPtr->screenDevice;
  354.             suppliedGDevice = true;
  355.         }
  356.         else
  357.         {
  358.             walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // for everybody
  359.             suppliedGDevice = false;
  360.         }
  361.         
  362.         myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);    // for DM2.0 searches
  363.     
  364.         // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
  365.         // ...now do the loop if we can start
  366.         if( walkDevice && myModeIteratorProc) do // start the search
  367.         {
  368.             iCount++;        // GDevice we are looking at (just a counter)
  369.             if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )    // DM1.0 does not need this, but it fits in the loop
  370.             {
  371.                 theDisplayModeCount = 0;    // for DM2.0 searches
  372.                 if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  373.                 {
  374.                     // search NuBus & PCI the new kool way through Display Manager 2.0
  375.                     GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
  376.                     DMDisposeList(theDisplayModeList);    // now toss the lists for this gdevice and go on to the next one
  377.                 }
  378.                 else
  379.                 {
  380.                     // search NuBus only the old disgusting way through the slot manager
  381.                     GetRequestTheDM1Way (requestRecPtr, walkDevice);
  382.                 }
  383.             }
  384.         } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );    // go until no more gdevices
  385.         if( myModeIteratorProc )
  386.             DisposeRoutineDescriptor(myModeIteratorProc);
  387.         return (noErr);    // we were able to get the look for a match
  388.     }
  389.     return (-1);        // return a generic error
  390. }
  391.  
  392. void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
  393. {
  394.     AuxDCEHandle myAuxDCEHandle;
  395.     unsigned long    depthMode;
  396.     unsigned long    displayMode;
  397.     OSErr            error;
  398.     OSErr            errorEndOfTimings;
  399.     short            height;
  400.     short            jCount = 0;
  401.     Boolean            modeOk;
  402.     SpBlock            spAuxBlock;
  403.     SpBlock            spBlock;
  404.     unsigned long    switchFlags;
  405.     VPBlock            *vpData;
  406.     short            width;
  407.  
  408.     myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);    
  409.     spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
  410.     spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
  411.     spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
  412.     spBlock.spHwDev = 0;                                // we are going to get this pup
  413.     spBlock.spParamData = 1<<foneslot;                    // this slot, enabled, and it better be here.
  414.     spBlock.spTBMask = 3;                                // don't have constants for this yet
  415.     errorEndOfTimings = SGetSRsrc(&spBlock);            // get the spDrvrHW so we know the ID of this puppy. This is important
  416.                                                         // since some video cards support more than one display, and the spDrvrHW
  417.                                                         // ID can, and will, be used to differentiate them.
  418.     
  419.     if ( noErr == errorEndOfTimings )
  420.     {
  421.         // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
  422.         spBlock.spID = 0;                                // start at zero, 
  423.         spBlock.spTBMask = 2;                            // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
  424.         spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);    // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
  425.         spBlock.spCategory=catDisplay;
  426.         spBlock.spCType=typeVideo;
  427.         errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // but only on 7.0 systems, not a problem since we require DM1.0
  428.         
  429.         // now, loop through all the timings for this GDevice
  430.         if ( noErr == errorEndOfTimings ) do
  431.         {
  432.             // now, loop through all possible depth modes for this timing mode
  433.             displayMode = (unsigned char)spBlock.spID;    // "timing mode, ie:resource ref number"
  434.             for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
  435.             {
  436.                 depthMode = jCount;        // vid mode
  437.                 error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
  438.     
  439.                 // only if the mode is safe or we override it with the kAllValidModesBit request flag
  440.                 if (    noErr == error &&
  441.                         modeOk &&
  442.                         (    switchFlags & 1<<kNoSwitchConfirmBit ||
  443.                             requestRecPtr->requestFlags & 1<<kAllValidModesBit
  444.                         )
  445.                     )
  446.                 {
  447.                     // have a good displayMode/depthMode combo - now lets look inside
  448.                     spAuxBlock = spBlock;                // don't ruin the iteration spBlock!!
  449.                     spAuxBlock.spID = depthMode;        // vid mode
  450.                     error=SFindStruct(&spAuxBlock);        // get back a new spsPointer
  451.                     if (noErr == error)                    // keep going if no error…
  452.                     {
  453.                         spAuxBlock.spID = 0x01;            // mVidParams request
  454.                         error=SGetBlock (&spAuxBlock);    // use the new spPointer and get back...a NewPtr'ed spResult
  455.                         if (noErr == error)                // …keep going if no error…
  456.                         {                                // We have data! lets have a look
  457.                             vpData = (VPBlock*)spAuxBlock.spResult;
  458.                             height = vpData->vpBounds.bottom;    // left and top are usually zero
  459.                             width = vpData->vpBounds.right;
  460.                             
  461.                             if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
  462.                             {
  463.                                 requestRecPtr->screenDevice = walkDevice;
  464.                                 requestRecPtr->availBitDepth = vpData->vpPixelSize;
  465.                                 requestRecPtr->availHorizontal = vpData->vpBounds.right;
  466.                                 requestRecPtr->availVertical = vpData->vpBounds.bottom;
  467.                                 requestRecPtr->displayMode = displayMode;
  468.                                 requestRecPtr->depthMode = depthMode;
  469.                                 requestRecPtr->switchInfo.csMode = depthMode;                // fill in for completeness
  470.                                 requestRecPtr->switchInfo.csData = displayMode;
  471.                                 requestRecPtr->switchInfo.csPage = 0;
  472.                                 requestRecPtr->switchInfo.csBaseAddr = 0;
  473.                                 requestRecPtr->switchInfo.csReserved = 0;
  474.                                 if (switchFlags & 1<<kNoSwitchConfirmBit)
  475.                                     requestRecPtr->availFlags = 0;                            // mode safe
  476.                                 else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  477.                             }
  478.  
  479.                             if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);    // toss this puppy when done
  480.                         }
  481.                     }
  482.                 }
  483.             }
  484.             // go around again, looking for timing modes for this GDevice
  485.             spBlock.spTBMask = 2;        // ignore DrvrSW
  486.             spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);    // next resource, this slot, whether enabled or disabled
  487.             errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // and get the next timing mode
  488.         } while ( noErr == errorEndOfTimings );    // until the end of this GDevice
  489.     }
  490.  
  491. }
  492.  
  493. pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
  494. {
  495.     unsigned long            depthCount;
  496.     short                    iCount;
  497.     ListIteratorDataRec        *myIterateData        = (ListIteratorDataRec*) userData;
  498.     DepthInfo                *myDepthInfo;
  499.     
  500.     // set user data in a round about way
  501.     myIterateData->displayModeTimingInfo        = *displaymodeInfo->displayModeTimingInfo;
  502.     
  503.     // now get the DMDepthInfo info into memory we own
  504.     depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
  505.     myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
  506.  
  507.     // set the info for the caller
  508.     myIterateData->depthBlockCount = depthCount;
  509.     myIterateData->depthBlocks = myDepthInfo;
  510.  
  511.     // and fill out all the entries
  512.     if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
  513.     {
  514.         myDepthInfo[iCount].depthSwitchInfo = 
  515.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
  516.         myDepthInfo[iCount].depthVPBlock = 
  517.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
  518.     }
  519. }
  520.  
  521. void GetRequestTheDM2Way (    VideoRequestRecPtr requestRecPtr,
  522.                             GDHandle walkDevice,
  523.                             DMDisplayModeListIteratorUPP myModeIteratorProc,
  524.                             DMListIndexType theDisplayModeCount,
  525.                             DMListType *theDisplayModeList)
  526. {
  527.     short                    jCount;
  528.     short                    kCount;
  529.     ListIteratorDataRec        searchData;
  530.  
  531.     searchData.depthBlocks = nil;
  532.     // get the mode lists for this GDevice
  533.     for (jCount=0; jCount<theDisplayModeCount; jCount++)        // get info on all the resolution timings
  534.     {
  535.         DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
  536.         
  537.         // for all the depths for this resolution timing (mode)...
  538.         if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
  539.         {
  540.             // only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
  541.             if    (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
  542.                     (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
  543.                         requestRecPtr->requestFlags & 1<<kAllValidModesBit
  544.                     )
  545.                 )
  546.             {
  547.                 if (FindBestMatch (    requestRecPtr,
  548.                                     searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  549.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  550.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
  551.                 {
  552.                     requestRecPtr->screenDevice = walkDevice;
  553.                     requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
  554.                     requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
  555.                     requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
  556.                     
  557.                     // now set the important info for DM to set the display
  558.                     requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
  559.                     requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
  560.                     requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
  561.                     if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  562.                         requestRecPtr->availFlags = 0;                            // mode safe
  563.                     else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  564.     
  565.                 }
  566.             }
  567.  
  568.         }
  569.     
  570.         if (searchData.depthBlocks)
  571.         {
  572.             DisposePtr ((Ptr)searchData.depthBlocks);    // toss for this timing mode of this gdevice
  573.             searchData.depthBlocks = nil;                // init it just so we know
  574.         }
  575.     }
  576. }
  577.  
  578. Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
  579. {
  580.     // •• do the big comparison ••
  581.     // first time only if    (no mode yet) and
  582.     //                        (bounds are greater/equal or kMaximizeRes not set) and
  583.     //                        (depth is less/equal or kShallowDepth not set) and
  584.     //                        (request match or kAbsoluteRequest not set)
  585.     if    (    nil == requestRecPtr->displayMode
  586.             &&
  587.             (    (horizontal >= requestRecPtr->reqHorizontal &&
  588.                 vertical >= requestRecPtr->reqVertical)
  589.                 ||                                                        
  590.                 !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)    
  591.             )
  592.             &&
  593.             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  594.                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  595.             )
  596.             &&
  597.             (    (horizontal == requestRecPtr->reqHorizontal &&    
  598.                 vertical == requestRecPtr->reqVertical &&
  599.                 bitDepth == requestRecPtr->reqBitDepth)
  600.                 ||
  601.                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  602.             )
  603.         )
  604.         {
  605.             // go ahead and set the new values
  606.             return (true);
  607.         }
  608.     else    // can we do better than last time?
  609.     {
  610.         // if    (kBitDepthPriority set and avail not equal req) and
  611.         //        ((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
  612.         //        (avail depth less reqested and new greater avail)
  613.         //        (request match or kAbsoluteRequest not set)
  614.         if    (    (    requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
  615.                     requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
  616.                 )
  617.                 &&
  618.                 (    (    bitDepth > requestRecPtr->availBitDepth &&
  619.                         bitDepth <= requestRecPtr->reqBitDepth
  620.                     )
  621.                     ||
  622.                     !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)    
  623.                 )
  624.                 &&
  625.                 (    requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  626.                     bitDepth > requestRecPtr->availBitDepth    
  627.                 )
  628.                 &&
  629.                 (    (horizontal == requestRecPtr->reqHorizontal &&    
  630.                     vertical == requestRecPtr->reqVertical &&
  631.                     bitDepth == requestRecPtr->reqBitDepth)
  632.                     ||
  633.                     !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  634.                 )
  635.             )
  636.         {
  637.             // go ahead and set the new values
  638.             return (true);
  639.         }
  640.         else
  641.         {
  642.             // match resolution: minimize Δh & Δv
  643.             if    (    abs((requestRecPtr->reqHorizontal - horizontal)) <=
  644.                     abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
  645.                     abs((requestRecPtr->reqVertical - vertical)) <=
  646.                     abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
  647.                 )
  648.             {
  649.                 // now we have a smaller or equal delta
  650.                 //    if (h or v greater/equal to request or kMaximizeRes not set) 
  651.                 if (    (horizontal >= requestRecPtr->reqHorizontal &&
  652.                         vertical >= requestRecPtr->reqVertical)
  653.                         ||
  654.                         !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
  655.                     )
  656.                 {
  657.                     // if    (depth is equal or kBitDepthPriority not set) and
  658.                     //        (depth is less/equal or kShallowDepth not set) and
  659.                     //        ([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
  660.                     //        (request match or kAbsoluteRequest not set)
  661.                     if    (    (    requestRecPtr->availBitDepth == bitDepth ||            
  662.                                 !(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
  663.                             )
  664.                             &&
  665.                             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  666.                                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  667.                             )
  668.                             &&
  669.                             (    (requestRecPtr->availHorizontal != horizontal ||
  670.                                 requestRecPtr->availVertical != vertical)
  671.                                 ||
  672.                                 (requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  673.                                 bitDepth > requestRecPtr->availBitDepth)
  674.                                 ||
  675.                                 (bitDepth == requestRecPtr->reqBitDepth)
  676.                             )
  677.                             &&
  678.                             (    (horizontal == requestRecPtr->reqHorizontal &&    
  679.                                 vertical == requestRecPtr->reqVertical &&
  680.                                 bitDepth == requestRecPtr->reqBitDepth)
  681.                                 ||
  682.                                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  683.                             )
  684.                         )
  685.                     {
  686.                         // go ahead and set the new values
  687.                         return (true);
  688.                     }
  689.                 }
  690.             }
  691.         }
  692.     }
  693.     return (false);
  694. }
  695.  
  696. void GravitateMonitors (void)
  697. {
  698.     // do the magic gravitation here
  699. }